package botvn;

import botvn.libraries.LoggingUtils;
import botvn.libraries.Utils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.ProtocolException;
import org.apache.http.client.CookieStore;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.client.DefaultRedirectStrategy;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.util.EntityUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.http.HeaderIterator;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.ex.HttpClientRequest;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.protocol.HttpClientContext;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.protocol.HTTP;

public class HttpUtil {

    private static final PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

    private static CloseableHttpClient mClient = null;

    /**
     * Creates HTTP client. Uses Firefox User-Agent to fool Facebook. Sets
     * cookies from provided CookieStore.
     */
    private static CloseableHttpClient createHttpLocalClient(CookieStore cookieStore) {
        if (mClient == null) {
            HttpClientContext cc = HttpClientContext.create();
            cc.setCookieStore(cookieStore);
            //RequestConfig globalConfig = RequestConfig.custom().setCookieSpec(CookieSpecs.BEST_MATCH).build();
            mClient = HttpClients.custom().setConnectionManager(cm).setDefaultCookieStore(cookieStore).build();
            HttpClients.custom().setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:35.0) Gecko/20100101 Firefox/35.0");

            //CloseableHttpClient client = HttpClients.custom().setConnectionManager(cm).setDefaultCookieStore(cookieStore).build();
            //HttpClients.custom().setUserAgent("Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:33.0) Gecko/20100101 Firefox/33.0");
        }
        return mClient;
    }

    /**
     * Creates HTTP client. Uses Firefox User-Agent to fool Facebook. Sets
     * cookies from provided CookieStore.
     */
    @Deprecated
    private static DefaultHttpClient createHttpClient(CookieStore cookieStore) {
        DefaultHttpClient httpclient = new DefaultHttpClient();

        HttpProtocolParams.setUserAgent(httpclient.getParams(), "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:9.0.1) Gecko/20100101 Firefox/9.0.1");

        if (cookieStore != null) {
            httpclient.setCookieStore(cookieStore);
        }
        return httpclient;
    }

    /**
     * Sends GET request.
     */
    public static Response getLocal(String url, CookieStore cookieStore, boolean setdelay) throws IOException, InterruptedException {
        CloseableHttpClient client = createHttpLocalClient(cookieStore);
        HttpClientContext context = HttpClientContext.create();
        try {
            HttpGet httpget = new HttpGet(url);
            httpget.addHeader("Charset", "UTF-8");
            CloseableHttpResponse response = client.execute(httpget, context);

            HttpEntity entity = response.getEntity();
            if (entity == null) {
                return null;
            }
            String content = EntityUtils.toString(entity);
            Response r = new Response(content, response.getStatusLine(), context.getCookieStore());
            
            // Get all headers
            HttpResponse rr = context.getResponse();
            HeaderIterator headers = rr.headerIterator();
            while (headers.hasNext()) {
                System.out.println(headers.next());
            }
            if (setdelay) {
                int delay = Utils.randSec(Constants.MIN_DELAY_REQUEST, Constants.MAX_DELAY_REQUEST);
                LoggingUtils.print(String.format("Delay: %ds", delay));
                Thread.sleep(delay);
            }
            return r;
        } finally {
        }
    }

    /**
     * Sends GET request.
     */
    @Deprecated
    public static Response get(String url, CookieStore cookieStore) throws IOException {
        DefaultHttpClient httpclient = createHttpClient(cookieStore);

        HttpGet httpget = new HttpGet(url);
        HttpResponse response = httpclient.execute(httpget);

        HttpEntity entity = response.getEntity();
        if (entity == null) {
            return null;
        }

        String content = EntityUtils.toString(entity);
        httpclient.getConnectionManager().shutdown();
        return new Response(content, response.getStatusLine(), httpclient.getCookieStore());
    }

    /**
     * Sends POST request.
     * @param action
     * @param parameters
     * @param cookieStore
     * @param setdelay
     * @return 
     * @throws java.io.IOException
     * @throws java.lang.InterruptedException
     */
    public static Response postLocal(String action, Map<String, String> parameters, CookieStore cookieStore, boolean setdelay) throws IOException, InterruptedException {
        CloseableHttpClient client = createHttpLocalClient(cookieStore);
        HttpClientContext context = HttpClientContext.create();
        context.setCookieStore(cookieStore);

        HttpClientRequest httpPost = new HttpClientRequest(action);
        httpPost.setDebugMode(LoggingUtils.DEBUG);
        List<NameValuePair> nvps = new ArrayList<>();
        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            String name = entry.getKey();
            if (name == null) {
                continue;
            }
            String value = entry.getValue();
            nvps.add(new BasicNameValuePair(name, value));
        }
        
        httpPost.setEntity(nvps);
        System.out.println("uri:" + httpPost.getURI().toString());
        RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(30 * 1000).setConnectTimeout(30 * 1000).build();
        httpPost.setConfig(requestConfig);

        context.setRequestConfig(requestConfig);
        HttpResponse response = client.execute(httpPost, context);
        response = context.getResponse();

        HeaderIterator headers = response.headerIterator();
        while (headers.hasNext()) {
            System.out.println(headers.next());
        }
        

        HttpEntity entity = response.getEntity();
        if (entity == null) {
            return null;
        }
        String content = EntityUtils.toString(entity);
        if (setdelay) {
            int delay = Utils.randSec(Constants.MIN_DELAY_REQUEST, Constants.MAX_DELAY_REQUEST);
            LoggingUtils.print(String.format("Delay: %ds", delay));
            Thread.sleep(delay);
        }
        return new Response(content, response.getStatusLine(), context.getCookieStore());
    }

    /**
     * Sends POST request.
     */
    @Deprecated
    public static Response post(String action, Map<String, String> parameters, CookieStore cookieStore) throws IOException, InterruptedException {
        DefaultHttpClient httpclient = createHttpClient(cookieStore);

        httpclient.setRedirectStrategy(new DefaultRedirectStrategy() {
            public boolean isRedirected(HttpRequest request, HttpResponse response, HttpContext context) {
                boolean isRedirect = false;
                try {
                    isRedirect = super.isRedirected(request, response, context);
                } catch (ProtocolException e) {
                    e.printStackTrace();
                }
                if (!isRedirect) {
                    int responseCode = response.getStatusLine().getStatusCode();
                    if (responseCode == 301 || responseCode == 302) {
                        return true;
                    }
                }
                return isRedirect;
            }
        });

        HttpPost httpPost = new HttpPost(action);

        List<NameValuePair> nvps = new ArrayList<NameValuePair>();
        for (Map.Entry<String, String> entry : parameters.entrySet()) {
            String name = entry.getKey();
            if (name == null) {
                continue;
            }
            String value = entry.getValue();
            nvps.add(new BasicNameValuePair(name, value));
        }

        httpPost.setEntity(new UrlEncodedFormEntity(nvps));
        HttpResponse response = httpclient.execute(httpPost);

        HttpEntity entity = response.getEntity();
        if (entity == null) {
            return null;
        }

        String content = EntityUtils.toString(entity);
        httpclient.getConnectionManager().shutdown();
        Thread.sleep(Utils.randSec(10, 30));
        return new Response(content, response.getStatusLine(), httpclient.getCookieStore());
    }
}
